﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;

using Cards.Objects;
using Cards.Util;

namespace Cards.GUI
{
    public partial class INS_Stage : UserControl
    {
        protected int x;
        protected int y;
        protected int m_width;
        protected int m_height;
        protected int m_numOfPlayers;
        protected CStage m_stage;
        protected INS_PackOfCards m_insPackOfCards;
        protected INS_Player[] m_insPlayer;
        protected Form m_winParent;
        protected Button m_btnPlay;
        protected Button m_btnSkip;
        protected Button btnContinue;
        protected Button m_btnSortCards;

        public ArrayList m_previousCard = new ArrayList();
        public ArrayList m_currentCard = new ArrayList();
        public ArrayList arrivedPlayers = new ArrayList();

        public static int sSide = 0;
        public static Boolean sBeginPlaying = true;
        public static INS_Player sFirstPlayingPlayer = null;
        public static Boolean sPlay = false;
        public static long sBetMoney = 1000; 
        
        protected int m_numOfCards; //so luong quan bai ban dau
        protected int m_maxNumOfCards; //so luong quan bai toi da

        private PictureBox m_picMovingCard;
        private Point m_pOCLoc;
        private Timer m_movingTimer;
        private EDISTRIBUTE_MODE m_distributeMode;

        public int X
        {
            get { return x; }
            set { x = value; }
        }
        public int Y
        {
            get { return y; }
            set { y = value; }
        }
        public int WIDTH
        {
            get { return m_width; }
            set { m_width = value; }
        }
        public int HEIGHT
        {
            get { return m_height; }
            set { m_height = value; }
        }
        public INS_PackOfCards IPC{
            get { return m_insPackOfCards; }
            set { m_insPackOfCards = value; }
        }
        public CStage STAGE
        {
            get { return m_stage; }
            set { m_stage = value; }
        }
        public int NUMPLAYERS
        {
            get { return m_numOfPlayers; }
            set { m_numOfPlayers = value; }
        }
        public INS_Player this[int index]{
            get
            {
                if ((index < 0) || (index > m_insPlayer.Length))
                {
                    return null;
                }
                else
                {
                    return m_insPlayer[index];
                }
            }
            set
            {
                if (index >= 0 && index < m_insPlayer.Length)
                {
                    m_insPlayer[index] = value;
                }
            }
        }

        public Point POCLOC
        {
            get { return m_pOCLoc; }
            set { m_pOCLoc = value; }
        }

        public INS_Stage()
        {
            InitializeComponent();
        }

        public virtual void Init()
        {
            this.Size = new Size(new Point(m_width, m_height));
            this.Location = new Point(x, y);

            sSide = 0;
            sBeginPlaying = true;

            m_movingTimer = new System.Windows.Forms.Timer();
            m_movingTimer.Interval = 1;
            m_movingTimer.Tick += new System.EventHandler(movingTimer_Tick);
            m_distributeMode = EDISTRIBUTE_MODE.ALL;
        }

        
        public virtual void BeginToPlay()
        {
            sPlay = true;
            m_insPackOfCards.MergeCards();
        }

        public virtual void BeginNetworkPlaying()
        {
            sPlay = true;
            m_insPackOfCards.MergeCards();
        }

        public virtual void PlayNetworkingNextStage()
        {
        }

        public void ContinueToPlay()
        {
            InitToContinuePlay();
            PlayNextStage();
        }

        public virtual void InitToContinuePlay()
        {
        }

        public virtual void PlayNextStage()
        {
        }

        public virtual void CreateGUIToReplay()
        {
        }
        
        public void CreateGUI()
        {
            CreatePlayerGUI();
            CreatePackOfCardsGUI();
            CreateButton();
            CreateMovingCardGUI();
        }

        public void CreateMovingCardGUI()
        {
            m_pOCLoc = new Point((Constants.s_playerWidth / 2) + IPC.POCLOC.X,
                                                 Constants.s_playerHeight + Constants.s_alphay + IPC.POCLOC.Y);
            m_picMovingCard = new PictureBox();
            m_picMovingCard.Size = new Size(Constants.s_cardWidth, Constants.s_cardHeight);
            m_picMovingCard.Location = new Point((Constants.s_playerWidth / 2) + IPC.POCLOC.X,
                                                 Constants.s_playerHeight + Constants.s_alphay + IPC.POCLOC.Y);
            m_picMovingCard.Image = global::Cards.Properties.Resources.bobai2;
            m_picMovingCard.SizeMode = PictureBoxSizeMode.StretchImage;
            this.Controls.Add(m_picMovingCard);
            m_picMovingCard.Visible = false;
            m_picMovingCard.BringToFront();
        }

        public void CreatePackOfCardsGUI(){
            m_insPackOfCards.CreateGUI();
            this.Controls.Add(m_insPackOfCards);
            m_insPackOfCards.BringToFront();
        }

        
        public virtual void CreatePlayerGUI()
        {
        }

        public virtual void CreateButton()
        {
            Button btnClose = new Button();
            btnClose.Text = "Đóng";
            btnClose.Size = new Size(new Point(80, 22));
            btnClose.BackColor = Color.DarkMagenta;
            btnClose.ForeColor = Color.White;
            btnClose.Location = new Point(Constants.s_tableWidth - 90,
                                         Constants.s_playerHeight * 2
                                         + Constants.s_cardContainerHeight + 21);
            btnClose.Click += new EventHandler(btnClose_click);
            this.Controls.Add(btnClose);

            btnContinue = new Button();
            btnContinue.Text = "Chơi tiếp";
            btnContinue.Size = new Size(new Point(120, 50));
            btnContinue.Location = new Point(m_insPackOfCards.Width / 2 - 65, m_insPackOfCards.Height / 2 - 20);
            btnContinue.BackColor = Color.DarkMagenta;
            btnContinue.Click += new EventHandler(btnContinue_click);
            btnContinue.BringToFront();
            btnContinue.Visible = false;
            m_insPackOfCards.Controls.Add(btnContinue);
        }

        public void enableButtonPlay(Boolean _state)
        {
            m_btnPlay.Enabled = _state;
        }

        public void enableButtonSkip(Boolean _state)
        {
            m_btnSkip.Enabled = _state;
        }

        protected void btnPlay_click(object sender, EventArgs e)
        {
            Step();
        }

        protected void btnSkip_click(object sender, EventArgs e)
        {
            Skip();
        }

        public virtual void Step()
        {
        }

        public virtual void Skip()
        {
        }

        private void btnClose_click(object sender, EventArgs e)
        {
            m_winParent.Close();
        }

        private void btnContinue_click(object sender, EventArgs e)
        {
            ContinueToPlay();
            btnContinue.Visible = false;
        }

        
        public void SortCards()
        {
            for (int i = 0; i < m_numOfPlayers; i++)
            {
                m_insPlayer[i].SortCards();
                m_insPlayer[i].DeselectAllCards();
                m_insPlayer[i].MoveCards();
            }
        }

        //Xoa van bai truoc khi tao van bai moi
        public void DeleteStage()
        {
            for (int i = 0; i < NUMPLAYERS; i++)
            {
                m_insPlayer[i].DeleteCards();
                this.Controls.Remove(m_insPlayer[i]);
                m_insPlayer[i].Dispose();
                this.Controls.Remove(m_insPackOfCards);
                m_insPackOfCards.Dispose();
            }
        }

        /// <summary>
        /// End the stage
        /// </summary>
        public virtual void EndStage()
        {
            m_insPlayer[sSide].EndTurn();

            Stop();

            m_picMovingCard.Visible = false;

            if ((MainFrame.s_multiType == MULTI_PLAYER_TYPE.SINGLE_PLAYER)
                || (MainFrame.s_multiType == MULTI_PLAYER_TYPE.MULTI_PLAYER_SERVER))
            {
                btnContinue.Visible = true;
                btnContinue.BringToFront();
            }
        }

        public void Stop()
        {
            sPlay = false;
            timerStartStage.Enabled = false;
            timerStartStage.Stop();
            m_movingTimer.Stop();
            m_movingTimer.Enabled = false;
            STAGE.Stop();
        }

        protected virtual void timer1_Tick(object sender, EventArgs e)
        {

        }

        public virtual void AddMoneyForTotalWin(int _posPlayer)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        #region Distributing cards for players

        private int m_moveffCurrentPlayer;
        private int m_moveffCurrentCardIndex;
        private int m_moveffDeltaX;
        private int m_moveffDeltaY;
        private Point m_moveffCurrentDestinationPoint = new Point(0, 0);
        private Point m_moveffCurrentPoint = new Point(0, 0);
        private EDIRECTIONS m_moveffDirection;

        public void CardsDistributionEffect()
        {
            LockGUI();
            m_distributeMode = EDISTRIBUTE_MODE.ALL;

            m_picMovingCard.Visible = true;
            m_picMovingCard.BringToFront();

            m_moveffCurrentPlayer = 0;
            m_moveffCurrentCardIndex = 0;
            m_moveffDeltaX = 0;
            m_moveffDeltaY = 0;

            ComputeMoveff();
            
            m_movingTimer.Start();
            m_movingTimer.Enabled = true;
        }

        public void OneCardDistributionEffect(int _playerIdx, int _cardIdx)
        {
            m_moveffCurrentPlayer = _playerIdx;
            m_moveffCurrentCardIndex = _cardIdx;

            if (this[m_moveffCurrentPlayer].PLAYERKIND == PLAYER_TYPE.HUMAN)
            {
                LockGUI();
            }
            m_distributeMode = EDISTRIBUTE_MODE.ONE_CARD;

            m_picMovingCard.Visible = true;
            m_picMovingCard.BringToFront();

            m_moveffDeltaX = 0;
            m_moveffDeltaY = 0;

            ComputeMoveff();

            m_movingTimer.Start();
            m_movingTimer.Enabled = true;
        }

        private void ComputeMoveff()
        {
            INS_Player currPlayer = this[m_moveffCurrentPlayer];
            Point currCardLocation = new Point(currPlayer[m_moveffCurrentCardIndex].X, currPlayer[m_moveffCurrentCardIndex].Y);

            m_moveffCurrentDestinationPoint.X = currPlayer.X + currCardLocation.X;
            m_moveffCurrentDestinationPoint.Y = currPlayer.Y + currCardLocation.Y;

            m_moveffCurrentPoint.X = m_pOCLoc.X;
            m_moveffCurrentPoint.Y = m_pOCLoc.Y;

            m_moveffDirection = ComputeMoveffDirection(m_moveffCurrentDestinationPoint, m_moveffCurrentPoint);

            m_moveffDeltaX = Math.Abs(m_moveffCurrentDestinationPoint.X - m_moveffCurrentPoint.X) / 15;
            m_moveffDeltaY = Math.Abs(m_moveffCurrentDestinationPoint.Y - m_moveffCurrentPoint.Y) / 15;
        }

        private EDIRECTIONS ComputeMoveffDirection(Point _des, Point _curr)
        {
            if ((_des.X < _curr.X) && (_des.Y < _curr.Y))
            {
                return EDIRECTIONS.D_NW;
            }
            else if ((_des.X > _curr.X) && (_des.Y < _curr.Y))
            {
                return EDIRECTIONS.D_NE;
            }
            else if ((_des.X > _curr.X) && (_des.Y > _curr.Y))
            {
                return EDIRECTIONS.D_SE;
            }
            else if ((_des.X < _curr.X) && (_des.Y > _curr.Y))
            {
                return EDIRECTIONS.D_SW;
            }

            return EDIRECTIONS.D_SW;
        }

        protected void movingTimer_Tick(object sender, EventArgs e)
        {
            bool arrivedCardFlag = false;

            switch (m_moveffDirection)
            {
                case EDIRECTIONS.D_NW:
                    Point p = m_picMovingCard.Location;
                    p.X -= m_moveffDeltaX;
                    p.Y -= m_moveffDeltaY;
                    m_picMovingCard.Location = p;

                    if ((m_picMovingCard.Location.X <= m_moveffCurrentDestinationPoint.X)
                        || ((m_picMovingCard.Location.Y <= m_moveffCurrentDestinationPoint.Y)))
                    {
                        arrivedCardFlag = true;
                    }
                    break;

                case EDIRECTIONS.D_NE:
                    p = m_picMovingCard.Location;
                    p.X += m_moveffDeltaX;
                    p.Y -= m_moveffDeltaY;
                    m_picMovingCard.Location = p;

                    if ((m_picMovingCard.Location.X >= m_moveffCurrentDestinationPoint.X)
                        || ((m_picMovingCard.Location.Y <= m_moveffCurrentDestinationPoint.Y)))
                    {
                        arrivedCardFlag = true;
                    }
                    break;

                case EDIRECTIONS.D_SE: 
                    p = m_picMovingCard.Location;
                    p.X += m_moveffDeltaX;
                    p.Y += m_moveffDeltaY;
                    m_picMovingCard.Location = p;

                    if ((m_picMovingCard.Location.X >= m_moveffCurrentDestinationPoint.X)
                        || ((m_picMovingCard.Location.Y >= m_moveffCurrentDestinationPoint.Y)))
                    {
                        arrivedCardFlag = true;
                    }
                    break;

                case EDIRECTIONS.D_SW: 
                    p = m_picMovingCard.Location;
                    p.X -= m_moveffDeltaX;
                    p.Y += m_moveffDeltaY;
                    m_picMovingCard.Location = p;

                    if ((m_picMovingCard.Location.X <= m_moveffCurrentDestinationPoint.X)
                        || ((m_picMovingCard.Location.Y >= m_moveffCurrentDestinationPoint.Y)))
                    {
                        arrivedCardFlag = true;
                    }
                    break;
            }

            if (arrivedCardFlag)
            {
                if (m_distributeMode == EDISTRIBUTE_MODE.ONE_CARD)
                {
                    FinishOneCardDistEff();
                }
                else
                {
                    FinishOneOfCardsDistEff();
                }
            }
        }

        public void FinishOneOfCardsDistEff()
        {
            m_picMovingCard.Location = m_moveffCurrentDestinationPoint;

            if (MainFrame.s_multiType == MULTI_PLAYER_TYPE.SINGLE_PLAYER)
            {
                if (this[m_moveffCurrentPlayer].PLAYERKIND == PLAYER_TYPE.HUMAN)
                {
                    this[m_moveffCurrentPlayer].DisplayCardAtPosition(m_moveffCurrentCardIndex);
                }
                else
                {
                    this[m_moveffCurrentPlayer].DisplayGCardAtPosition(m_moveffCurrentCardIndex);
                }
            }
            else
            {
                if ((this[m_moveffCurrentPlayer].PLAYERKIND == PLAYER_TYPE.HUMAN) 
                    && (this[m_moveffCurrentPlayer].STT == MainFrame.m_frmMultiGame.GAMEPLAYERID - 1))
                {
                    this[m_moveffCurrentPlayer].DisplayCardAtPosition(m_moveffCurrentCardIndex);
                }
                else
                {
                    this[m_moveffCurrentPlayer].DisplayGCardAtPosition(m_moveffCurrentCardIndex);
                }
            }

            m_picMovingCard.Location = POCLOC;

            m_moveffCurrentPlayer++;

            if (m_moveffCurrentPlayer >= m_numOfPlayers)
            {
                m_moveffCurrentPlayer = 0;
                m_moveffCurrentCardIndex++;
            }

            if (m_moveffCurrentCardIndex >= m_numOfCards)
            {
                m_movingTimer.Stop();
                UnLockGUI();
                EndDistributeCardsEffect();
            }
            else
            {
                ComputeMoveff();
            }
        }

        public void FinishOneCardDistEff()
        {
            m_movingTimer.Stop();

            m_picMovingCard.Location = m_moveffCurrentDestinationPoint;

            if (this[m_moveffCurrentPlayer].PLAYERKIND == PLAYER_TYPE.HUMAN)
            {
                this[m_moveffCurrentPlayer].DisplayCardAtPosition(m_moveffCurrentCardIndex);
            }
            else
            {
                this[m_moveffCurrentPlayer].DisplayGCardAtPosition(m_moveffCurrentCardIndex);
            }

            m_picMovingCard.Visible = false;
            m_picMovingCard.Location = POCLOC;

            if (this[m_moveffCurrentPlayer].PLAYERKIND == PLAYER_TYPE.HUMAN)
            {
                UnLockGUI();
            }

            if (this[m_moveffCurrentPlayer].NUMOFCARDS >= this[m_moveffCurrentPlayer].MAXNUMOFCARDS)
            {
                Skip();
            }

            if (STAGE.PENDINGENDSTAGE)
            {
                EndStage();
                STAGE.PENDINGENDSTAGE = false;
            }
            else if (STAGE.PENDINGSKIP)
            {
                STAGE.Skip();
                STAGE.PENDINGSKIP = false;
            }
        }

        public virtual void LockGUI()
        {
            m_btnPlay.Enabled = false;
            m_btnSkip.Enabled = false;
        }

        public virtual void UnLockGUI()
        {
            m_btnPlay.Enabled = true;
            m_btnSkip.Enabled = true;
        }

        /// <summary>
        /// End of distributing cards. Start playing
        /// </summary>
        public virtual void EndDistributeCardsEffect()
        {
            timerStartStage.Start();
            timerStartStage.Enabled = true;
            m_picMovingCard.Visible = false;

            for (int i = 0; i < NUMPLAYERS; i++)
            {
                if (this[i].PLAYERKIND == PLAYER_TYPE.COMPUTER)
                {
                    this[i].SortCards();
                    m_insPlayer[i].MoveCards();
                }

                // testing GUI, comment it when finished
                //this[i].DisplayCards();
            }
        }
        #endregion

        #region network playing

        public void OnReceiveMove(int _id, int[] _arrCards, Boolean _isServer)
        {
            INS_Stage.sSide = _id;

            this[_id].DeselectAllCards();

            for (int i = 0; i < _arrCards.Length; i++)
            {
                for (int j = 0; j < Constants.VNPOCKER_NUMOFCARDS; j++)
                {
                    if ((this[_id].IC[j].CARD.CARDTYPE == _arrCards[i]) && (!this[_id].IC[j].CARD.PLAY))
                    {
                        this[_id].IC[j].SelectCard();
                    }
                }
            }

            this[_id].INSSTAGE.STAGE.Play(true, _id);
        }

        public void OnReceiveSkip(int _id, Boolean _isServer)
        {
            INS_Stage.sSide = _id;

            this[_id].INSSTAGE.STAGE.Skip(true, _id);
        }

        public void OnContinueGame()
        {
            ContinueToPlay();
        }

        #endregion network playing

    }
}
